/**
 *  @file DLHook.h
 */

#ifndef _DLHOOK_H_
#define _DLHOOK_H_

#include "NoCopyAndNew.h"

namespace cppflib
{


/**
 *  @def GETORGPTR(ORGTYPE, pField, pEntry)
 *
 *  @brief 
 *
 *  <pre>
 *  A macro to retrieve the pointer to the original structure in which the
 *  following doubly-linked list structure is embedded.
 *  The idea is just to subtract the offset of the doubly-linked list within
 *  the original structure from the address of the doubly-linked list.
 *
 *  Originally, the offset part was 
 *
 *       (&(((ORGTYPE*)0)->pField))
 *
 *  but it will generate a warning by g++ when used in C++ class. So the '0x100' is used
 *  to avoid deferencing NULL. '0x100' is just an arbitrary number and can be any other.
 *  
 *  @a ORGTYPE -- data type of the original structure
 *  @a pField -- name of doubly-linked list field within the original structure
 *  @a pEntry -- address of the doubly-linked list
 *  </pre>
 */
#define GETORGPTR(ORGTYPE, pField, pEntry) \
            reinterpret_cast<ORGTYPE*>(reinterpret_cast<ptr_t>(pEntry) - \
                                       (reinterpret_cast<ptr_t>(&((reinterpret_cast<ORGTYPE*>(0x100))->pField)) - \
                                        0x100))

/**
 *  @brief A class to link up structures using doubly-linked list.  
 *
 *  <pre>
 *  It is a class, to be embedded in another class/structure, with some common 
 *  operations of a doubly linked list: adding, retrieving and deleting a entry.
 *  This doubly-linked list assumes there are 2 pointers pointing at 
 *  the head and tail
 *  </pre>
 */
class _DLLAPI DLHook : public NoCopy
{
public:
	DLHook(void);
	~DLHook(void);
public:
	void AddEntryToHead(DLHook ** pHead, DLHook ** pTail);
	void AddEntryToTail(DLHook ** pHead, DLHook ** pTail);
    void InsertEntry(DLHook * pPrevEntry, DLHook * pNextEntry);
	DLHook * GetNextEntry();
	DLHook * GetPrevEntry();	
	DLHook * DeleteEntry(DLHook ** pHead, DLHook ** pTail);
    void BreakupLink();

private:
    DLHook * m_pPrev; ///< points to previous entry
    DLHook * m_pNext; ///< points to next entry
};


} // end of namespace cppflib

#endif
